package com.qingxin.sys.utils;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import org.apache.commons.codec.binary.Base64;

/**
 * 加解密工具
 * @author Administrator
 *
 */
public class AESCipher {

	/**
	 * BASE64解码
	 * @param base64String
	 * @return
	 */
	public static byte[] decodeBASE64(String base64String){
		return Base64.decodeBase64(base64String);
	}
	
	
	/**
	 * BASE64编码
	 * @param binaryData
	 * @return
	 */
	public static String encodeBASE64(byte[] binaryData){
		return Base64.encodeBase64String(binaryData);
	}
	
	
	/**
	 * 将二进制数据以指定的基数编码为字符串
	 * @param binaryData
	 * @param radix 基数，有效值为[16~36]
	 * @return
	 */
	public static String binaryToString(byte[] binaryData, int radix) {
		if(radix<16 || radix>Character.MAX_RADIX){
			throw new IllegalArgumentException("编码基数["+radix+"]无效，有效值为[16~36]");
		}
		StringBuilder buf = new StringBuilder();
		for (int i = 0; i < binaryData.length; i++) {
			String s = Integer.toString(binaryData[i] & 0xFF, radix);
			if(s.length() == 1) {
				buf.append("0");
			}
			buf.append(s);
		}
		return buf.toString().toLowerCase();
	}
	
	
	/**
	 * 将使用指定基数编码的字符串解码为二进制数据（与binaryToString方法配合使用）
	 * @param stringData
	 * @param radix 基数，有效值为[16~36]
	 * @return
	 */
	public static byte[] stringToBinary(String stringData, int radix){
		if(radix<16 || radix>Character.MAX_RADIX){
			throw new IllegalArgumentException("编码基数["+radix+"]无效，有效值为[16~36]");
		}
		byte[] bytes = stringData.getBytes();
		int len = bytes.length;
		byte[] result = new byte[len/2];
		for (int i = 0; i < len; i += 2) {
			result[i/2] = (byte)Integer.parseInt(new String(bytes, i, 2), radix);
		}
		return result;
	}
	
	
	/**
	 * AES加密
	 * @param data 数据
	 * @param key 密码
	 * @return
	 * @throws Exception
	 */
	public static byte[] enAES(byte[] data, String key) throws Exception {
		SecretKey secretKey = generateAESKey(key);
		Cipher encryptCipher = Cipher.getInstance("AES");
		encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);
		return encryptCipher.doFinal(data);
	}
	
	
	/**
	 * AES解密
	 * @param data 数据
	 * @param key 密码
	 * @return
	 * @throws Exception
	 */
	public static byte[] deAES(byte[] data, String key) throws Exception {
		SecretKey secretKey = generateAESKey(key);
		Cipher decryptCipher = Cipher.getInstance("AES");
		decryptCipher.init(Cipher.DECRYPT_MODE, secretKey);
		return decryptCipher.doFinal(data);
	}
	
	
	/**
	 * AES加密并将结果编码为字符串
	 * @param data 数据
	 * @param key 密码
	 * @return
	 */
	public static String enAESToString(String data, String key) {
		try {
			byte[] encrypted = enAES(data.getBytes(), key);
			return binaryToString(encrypted, 36);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	
	/**
	 * AES解密一个用enAESToString方法生成的字符串
	 * @param data 数据
	 * @param key 密码
	 * @return
	 */
	public static String deAESFromString(String data, String key) {
		try {
			byte[] bin = stringToBinary(data, 36);
			byte[] decrypted = deAES(bin, key);
			return new String(decrypted);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * AES加密并将结果编码为BASE64字符串
	 * @param data 数据
	 * @param key 密码
	 * @return
	 */
	public static String enAESToBASE64(String data, String key) {
		try {
			byte[] encrypted = enAES(data.getBytes(), key);
			return encodeBASE64(encrypted);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * AES解密一个用enAESToBASE64方法生成的字符串
	 * @param data 数据
	 * @param key 密码
	 * @return
	 */
	public static String deAESFromBASE64(String data, String key) {
		try {
			byte[] bin = decodeBASE64(data);
			byte[] decrypted = deAES(bin, key);
			return new String(decrypted);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}
	
	
	/**
	 * 创建AES密钥
	 * @param key
	 * @return
	 * @throws NoSuchAlgorithmException 
	 */
	private static SecretKey generateAESKey(String key) throws NoSuchAlgorithmException {
		KeyGenerator generator = KeyGenerator.getInstance("AES");
		generator.init(128, new SecureRandom(key.getBytes()));
		return generator.generateKey();
	}
	
	
	
}
